using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Interfaces;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Wlmy.Ids4.Model.CommonModel;
using Wlmy.Ids4.Model.Model;

namespace Wlmy.Ids4.Model
{
    public class CustomDbContext : IdentityDbContext<User, Role, int, UserClaim,
    UserRole, IdentityUserLogin<int>,
    IdentityRoleClaim<int>, IdentityUserToken<int>>
    {
        public CustomDbContext(DbContextOptions<CustomDbContext> options)
            : base(options)
        {

        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            builder.Entity<UserRole>(userRole =>
            {
                userRole.HasKey(ur => new { ur.UserId, ur.RoleId });

                userRole.HasOne(ur => ur.Role)
                    .WithMany(r => r.UserRoles)
                    .HasForeignKey(ur => ur.RoleId)
                    .IsRequired();

                userRole.HasOne(ur => ur.User)
                    .WithMany(r => r.UserRoles)
                    .HasForeignKey(ur => ur.UserId)
                    .IsRequired();
            });
            builder.Entity<User>(user =>
            {
                user.HasMany(x => x.UserRoles).WithOne(x => x.User);
                user.HasMany(x => x.Claims).WithOne().HasForeignKey(x => x.UserId).IsRequired();
            });
            builder.Entity<Role>(role =>
            {
                role.HasMany(x => x.UserRoles).WithOne(x => x.Role);
            });
            var entityTypeList = builder.Model.GetEntityTypes().Where(x => x.ClrType.IsSubclassOf(typeof(Audit)));
            foreach (var entityType in entityTypeList)
            {
                var parameter = Expression.Parameter(entityType.ClrType);

                var propertyMethodInfo = typeof(EF).GetMethod("Property").MakeGenericMethod(typeof(bool));

                var isDeletedProperty = Expression.Call(propertyMethodInfo, parameter, Expression.Constant("IsDeleted"));

                BinaryExpression compareExpression = Expression.MakeBinary(ExpressionType.Equal, isDeletedProperty, Expression.Constant(false));

                var lambdaExpression = Expression.Lambda(compareExpression, parameter);

                builder.Entity(entityType.ClrType).HasQueryFilter(lambdaExpression);
            }
        }
    }
}
